package com.awx.server.dao.hibernate;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;

import org.hibernate.Criteria;
import org.hibernate.PropertyValueException;
import org.hibernate.criterion.Expression;

import com.awx.client.entities.Entity;
import com.awx.server.dao.DAO;
import com.awx.server.exception.InvalidValueException;
import com.awx.server.exception.ObjectNotFoundException;

public class HibernateDAO<T extends Entity> implements DAO {
	protected Class<T> c = null;
	
	public HibernateDAO(Class<T> c) {
		this.c = c;
	}
	
	public T findBy(Entity object) {
		return findById(object.getId());
	}

	public T findById(Long id) {
		T entity = c.cast(HibernateSessionFactory.getSession().load(c, id));
		
		if(entity == null){
			throw new ObjectNotFoundException(c, id);
		}
		return entity;
	}
	
	public T findById(String id) {
		try{
			return findById(Long.parseLong(id));
		} catch (NumberFormatException e) {
			throw new ObjectNotFoundException(c, -1L);	
		}
		
	}

	public void remove(Entity object) {
		HibernateSessionFactory.getSession().delete(object);
	}
	
	public Collection<T> findAll() {
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(c);
		return criteria.list();
	}
	
	public Collection<T> findByIds(Collection ids) {
		if (ids.isEmpty())
			return new HashSet<T>();
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(c);
		
		return criteria.add(Expression.in("id", ids)).list();
	}
	
	public Long store(Entity o) {
		try {
			Serializable ret = HibernateSessionFactory.getSession().save(o);
			if (ret instanceof Long){
				return (Long) ret;
			} else {
				return null;
			}
		} catch (PropertyValueException e) {
			throw new InvalidValueException(c, e.getPropertyName(), e);
		}
	}
	
	

}
